﻿using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using System.Reflection;

namespace LS.Screening.Core
{
    /// <summary>
    /// ActionExecuting上下文扩展类
    /// </summary>
    public static class ActionExecutingContextExtensions
    {
        /// <summary>
        /// 生成HttpRequest请求日志
        /// </summary>
        /// <param name="context"></param>
        /// <param name="attribute"></param>
        /// <returns></returns>
        public static RequestLog AddLog(this ActionExecutingContext context, HttpRequestEnableAttribute attribute)
        {
            RequestLog httpRequestLog = new RequestLog
            {
                AppType = attribute?.AppType,
                AppName = attribute?.AppName,
                ServiceName = context.Controller.GetType().FullName,
                MethodName = context.ActionDescriptor.RouteValues["action"],
                HttpMethod = context.HttpContext.Request.Method,
                Parameters = context.ActionArguments,
                LogLevel = LogLevel.Information,
                Tags = attribute?.Tags,
                ReturnValue = null
            };
            return httpRequestLog;
        }

        /// <summary>
        /// 判断是否启用请求日志
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public static Tuple<bool, T1> CheckIsEnable<T1, T2>(this ActionExecutingContext context)
            where T1 : LogAttribute
            where T2 : Attribute
        {
            if (!(context.ActionDescriptor is ControllerActionDescriptor))
                return new Tuple<bool, T1>(false, null);
            var methodInfo = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo;

            if (methodInfo == null)
            {
                return new Tuple<bool, T1>(false, null);
            }

            if (!methodInfo.IsPublic)
            {
                return new Tuple<bool, T1>(false, null);
            }

            if (methodInfo.IsDefined(typeof(T1), true))
            {
                var arrtibute = methodInfo.GetCustomAttributes<T1>(true).FirstOrDefault();
                return new Tuple<bool, T1>(true, arrtibute);
            }

            if (methodInfo.IsDefined(typeof(T2), true))
            {
                return new Tuple<bool, T1>(false, null);
            }

            var classType = methodInfo.DeclaringType;
            if (classType != null)
            {
                if (classType.IsDefined(typeof(T1), true))
                {
                    var arrtibute = classType.GetCustomAttributes<T1>(true).FirstOrDefault();
                    return new Tuple<bool, T1>(true, arrtibute);
                }

                if (classType.IsDefined(typeof(T2), true))
                {
                    return new Tuple<bool, T1>(false, null);
                }
            }
            return new Tuple<bool, T1>(false, null);
        }
    }
}
